<template>
  <div class="show-scene" ref="showSceneDiv"></div>

  <div id="bigScreen">
    <div class="member-info" v-if="curMemberInfo.name">
      <div class="cityEvent" :style="{
              backgroundImage: `url(${curMemberInfo.img})`
            }">
          
          <h1 style='padding-top:0.5rem'>姓名:<span>{{ curMemberInfo.name }}</span></h1>
          <h1>年龄:<span>{{curMemberInfo.age}}(岁)</span></h1>
          <h1>岗位:<span>{{curMemberInfo.work}}</span></h1>
      </div>
    </div>
    <div id="menu">
      <button id="table" @click="transform(targets.table, 2000)">
        表格展示
      </button>
      <button id="sphere" @click="transform(targets.sphere, 2000)">
        球体展示
      </button>
      <button id="helix" @click="transform(targets.helix, 2000)">
        螺旋展示
      </button>
      <button id="grid" @click="transform(targets.grid, 2000)">纵列展示</button>
    </div>
  </div>
</template>

<script setup>
import * as THREE from "three";
import { onMounted, reactive, ref } from "vue";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import TWEEN from "three/addons/libs/tween.module.js";

const showSceneDiv = ref(null);
const targets = reactive({ table: [], sphere: [], helix: [], grid: [] });
const objects = [];

let camera, scene, renderer, controls;

onMounted(() => {
  init();
  animate();
});

const curMemberInfo = ref({
  name: "",
  age: 0,
  work: "",
  img: "",
});

function init() {
  camera = new THREE.PerspectiveCamera(
    40,
    window.innerWidth / window.innerHeight,
    1,
    100000
  );
  camera.position.z = 3000;

  scene = new THREE.Scene();
  // 场景天空盒
  const textureCubeLoader = new THREE.CubeTextureLoader().setPath(
    "./textures/"
  );
  const textureCube = textureCubeLoader.load([
    "px.png",
    "nx.png",
    "py.png",
    "ny.png",
    "pz.png",
    "nz.png",
  ]);

  scene.background = textureCube;
  scene.environment = textureCube;

  // 生成补间动画
  gennerateTween();

  // 渲染器
  renderer = new THREE.WebGLRenderer();
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  showSceneDiv.value.appendChild(renderer.domElement);

  // 控制器
  controls = new OrbitControls(camera, renderer.domElement);
  controls.minDistance = 50;
  controls.maxDistance = 60000;
  // controls.minDistance = 5;
  // controls.maxDistance = 100;
  window.addEventListener("resize", onWindowResize);
  // 触发第一个table动画
  // transform(targets.table, 2000);
}

function getRandomInteger(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

const gennerateTween = () => {
  const group = new THREE.Group();
  const textureLoader = new THREE.TextureLoader().setPath("./textures/staff/");
  const imgUrls = [];
  for (let i = 1; i <= 18; i++) {
    imgUrls.push(`${i}.jpg`);
  }
  const materials = [];
  imgUrls.forEach((url) => {
    const texture = textureLoader.load(url);
    materials.push(
      new THREE.SpriteMaterial({ map: texture, transparent: false })
    );
    if (imgUrls.length === materials.length) {
      // 生成成员的个数
      const l = 100;
      // 生成随机贴图位置的点
      for (let i = 0; i < l; i++) {
        const random=getRandomInteger(0, materials.length - 1)
        const material = materials[random];
        const sprite = new THREE.Sprite(material);
        sprite.position.x = Math.random() * 4000 - 2000;
        sprite.position.y = Math.random() * 4000 - 2000;
        sprite.position.z = Math.random() * 4000 - 2000;
        sprite.scale.x = 200;
        sprite.scale.y = 250;
        const randomWork = [
          "前端",
          "后端",
          "输单(只打一遍)",
          "输单(打两遍第一遍)",
          "审单",
        ];
        sprite.freeObject = {
          name: `${i}号员工`,
          age: getRandomInteger(20,30),
          work: randomWork[Math.floor(Math.random() * 5)],
          img: `./textures/staff/${imgUrls[random]}`,
        };
        objects.push(sprite);
        // 创建射线
        const raycaster = new THREE.Raycaster();
        const mouse = new THREE.Vector2();
        // 事件的监听
        window.addEventListener("click", (event) => {
          mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
          mouse.y = -((event.clientY / window.innerHeight) * 2 - 1);

          raycaster.setFromCamera(mouse, camera);

          event.mesh = sprite;

          const intersects = raycaster.intersectObject(sprite);
          if (intersects.length > 0) {
            curMemberInfo.value = intersects[0].object.freeObject;
            // console.log("点击了",intersects[0]);
          }
        });
        group.add(sprite);
        // table的位置
        const sprite1 = new THREE.Sprite(material);
        // 每10个一行
        const length = Math.floor(i / 10) + 1;
        const length2 = (i % 10) + 1;
        sprite1.position.x = [length2] * 250 - 1530;
        sprite1.position.y = -[length] * 250 + 1300;
        sprite1.position.z = -1500;
        targets.table.push(sprite1);
        // 球
        const vector = new THREE.Vector3();
        const phi = Math.acos(-1 + (2 * i) / l);
        const theta = Math.sqrt(l * Math.PI) * phi;
        const object = new THREE.Object3D();
        object.position.setFromSphericalCoords(1500, phi, theta);
        vector.copy(object.position).multiplyScalar(2);
        object.lookAt(vector);
        targets.sphere.push(object);
        // 复制table的x,y的值,纵向观察
        const object1 = new THREE.Object3D();
        object1.position.x = sprite1.position.x;
        object1.position.y = sprite1.position.y;
        object1.position.z = Math.floor(i / 10) * 400 - 5500;
        targets.grid.push(object1);
        object1.lookAt(vector);
        // helix
        const theta1 = i * 0.175 + Math.PI;
        const y = -(i * 8) + 450;
        const object2 = new THREE.Object3D();
        object2.position.setFromCylindricalCoords(900, theta1, y);
        vector.x = object.position.x * 2;
        vector.y = object.position.y;
        vector.z = object.position.z * 2 - 500;
        object2.lookAt(vector);
        targets.helix.push(object2);
      }
      scene.add(group);
    }
  });
};
// 执行补间动画变化
function transform(targets, duration) {
  curMemberInfo.value = {
    name: "",
    age: 0,
    work: "",
    img: "",
  };
  TWEEN.removeAll();

  for (let i = 0; i < objects.length; i++) {
    const object = objects[i];
    const target = targets[i];

    new TWEEN.Tween(object.position)
      .to(
        { x: target.position.x, y: target.position.y, z: target.position.z },
        Math.random() * duration + duration
      )
      .easing(TWEEN.Easing.Exponential.InOut)
      .start();

    new TWEEN.Tween(object.rotation)
      .to(
        { x: target.rotation.x, y: target.rotation.y, z: target.rotation.z },
        Math.random() * duration + duration
      )
      .easing(TWEEN.Easing.Exponential.InOut)
      .start();
  }

  new TWEEN.Tween(this)
    .to({}, duration * 2)
    .onUpdate(render)
    .start();
}

// 监听窗口变化
function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}

// 动画帧
function animate() {
  requestAnimationFrame(animate);
  TWEEN.update();
  controls.update();
  render();
}
// 渲染器渲染
function render() {
  renderer.render(scene, camera);
}
</script>

<style>
#bigScreen {
  width: 100vw;
  height: 100vh;
  position: fixed;
  z-index: 100;

  left: 0;
  top: 0;
  pointer-events: none;
  display: flex;
  flex-direction: column;
}
.show-scene {
  width: 100vw;
  height: 100vh;
  position: fixed;
  z-index: 100;
  left: 0;
  top: 0;
}
a {
  color: #8ff;
}

#menu {
  position: fixed;
  bottom: 20px;
  width: 100%;
  text-align: center;
  pointer-events: none;
}

button {
  color: rgba(127, 255, 255, 0.75);
  background: transparent;
  outline: 1px solid rgba(127, 255, 255, 0.75);
  border: 0px;
  padding: 5px 10px;
  cursor: pointer;
  pointer-events: auto;
}

button:hover {
  background-color: rgba(0, 255, 255, 0.5);
}

button:active {
  color: #000000;
  background-color: rgba(0, 255, 255, 0.75);
}

.member-info{
  height: 100vh;
}

.cityEvent {
  position: relative;
  width: 4rem;
  /* height: 3rem; */
  background-image: url(@/assets/bg/bg_img03.png);
  background-repeat: no-repeat;
  background-size: 4rem;
  cursor: pointer;
  pointer-events: auto;
  height:100vh;
}

.cityEvent::before {
  width: 0.4rem;
  height: 0.4rem;
  position: absolute;
  left: 0;
  top: 0;
  border-top: 4px solid rgb(34, 133, 247);
  border-left: 4px solid rgb(34, 133, 247);
  content: "";
  display: block;
}

.cityEvent::after {
  width: 0.4rem;
  height: 0.4rem;
  position: absolute;
  right: 0;
  top: 0;
  border-top: 4px solid rgb(34, 133, 247);
  border-right: 4px solid rgb(34, 133, 247);
  content: "";
  display: block;
}

h1 {
  color: red;
  display: flex;
  font-weight:800;
  align-items: center;
  padding: 0 0.3rem 0.3rem;
  justify-content: flex-start;
  font-size: 0.3rem;
}
</style>
